package com.wxzhou.wangzhuan.service;

import com.wxzhou.wangzhuan.dto.*;
import com.wxzhou.wangzhuan.entity.SysUser;
import com.wxzhou.wangzhuan.entity.UserBindRelation;
import com.wxzhou.wangzhuan.exception.UserBindException;
import com.wxzhou.wangzhuan.repository.SysUserRepository;
import com.wxzhou.wangzhuan.util.NicknameGenerator;
import io.smallrye.mutiny.Uni;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import org.jboss.logging.Logger;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.Optional;

/**
 * 用户认证服务
 */
@ApplicationScoped
public class AuthService {

    private static final Logger LOG = Logger.getLogger(AuthService.class);

    @Inject
    SysUserRepository sysUserRepository;

    @Inject
    TokenService tokenService;

    /**
     * 设备登录
     *
     * @param deviceId
     * @param channel
     * @return
     */
    public Uni<LoginResponseDto> deviceLogin(String deviceId, String channel) {
        return sysUserRepository.findByDeviceId(deviceId,channel)
                .onItem().transformToUni(existingUser -> {
                    if (existingUser != null) {
                        //TODO：设备已存在，更新登录时间，写入到redis中，并发送消息，用于后续消费。
                        return createLogonToken(existingUser);
                    } else {
                        // 新设备，创建用户
                        SysUser newUser = createUserByDevice(deviceId, channel);
                        return sysUserRepository.create(newUser).onItem().transformToUni(createdUser -> createLogonToken(createdUser));
                    }
                });
    }

    /**
     * 绑定子账号
     *
     * @param bindRequestDto 绑定请求,含子账号
     * @param mainUser       主账号
     * @return 返回当前最新绑定数
     */
    public Uni<Integer> bindSubUser(BindRequestDto bindRequestDto, UserInfoDto mainUser) {
        return sysUserRepository.findById(mainUser.getUserId())
                .onItem().transformToUni(existingMainUser -> {
                    if (existingMainUser != null) {
                        if (!existingMainUser.getIs_enable() || !existingMainUser.getIs_main() || existingMainUser.getChild_max_count() == null || existingMainUser.getChild_max_count() <= 0)
                            throw new UserBindException("当前用户权限不足");
                        return sysUserRepository.findAllBindRecordById(existingMainUser.getId()).onItem().transformToUni(userBindRelations -> {
                            int bindAllCount = userBindRelations.size(); //已绑定数量
                            Optional<UserBindRelation> findSomeSubUser = userBindRelations.stream().filter(userBindRelation -> userBindRelation.getUserid().longValue() == bindRequestDto.getSubUserId().longValue()).findFirst();
                            if (findSomeSubUser.isPresent()) throw new UserBindException("用户已绑定");
                            if (existingMainUser.getChild_max_count() <= bindAllCount)
                                throw new UserBindException("绑定数量已超上限");
                            //todo:持久化绑定
                            return sysUserRepository.bindSubUserFromMainUser(bindRequestDto.getSubUserId(), mainUser.getUserId())
                                    .onItem().transformToUni(integer -> {
                                        return Uni.createFrom().item(bindAllCount + 1);
                                    }).onFailure().recoverWithUni(throwable -> Uni.createFrom().failure(() -> {
                                        LOG.errorf("提现异常，sysUserRepository.bindSubUserFromMainUser error！");
                                        return new UserBindException("绑定异常");
                                    }));
                        });
                    } else {
                        throw new UserBindException("绑定失败");
                    }
                });
    }

    /**
     * 分页查询用户子账号绑定记录
     *
     * @param pageRequest
     * @param currentUserInfo
     * @return
     */
    public Uni<PageResponseDto<BindRecordResponseDto>> getPageList(BindRecordRequestDto pageRequest, UserInfoDto currentUserInfo) {
        pageRequest.setUserid(currentUserInfo.getUserId());
        Uni<List<BindRecordResponseDto>> dataUni = sysUserRepository.findWithPagination(pageRequest);
        Uni<Long> countUni = sysUserRepository.countOf(pageRequest);
        return Uni.combine().all().unis(dataUni, countUni).asTuple().onItem().transform(tuple -> {
            List<BindRecordResponseDto> responseDtos = tuple.getItem1();
            Integer total = tuple.getItem2().intValue();
            return PageResponseDto.of(pageRequest.getPage(), pageRequest.getLimit(), total, responseDtos);
        });
    }

    /**
     * 获取当前用户绑定面板数据
     *
     * @param mainUser 当前主账号用户
     * @return
     */
    public Uni<BindDashboadResponseDto> getBindDashboard(UserInfoDto mainUser) {
        return sysUserRepository.findById(mainUser.getUserId())
                .onItem().transformToUni(existingMainUser -> {
                    if (existingMainUser != null) {
                        Long allBindCount = existingMainUser.getChild_max_count();
                        if (!existingMainUser.getIs_enable() || !existingMainUser.getIs_main() || allBindCount == null || allBindCount <= 0)
                            throw new UserBindException("当前用户权限不足");
                        return sysUserRepository.findAllBindRecordById(existingMainUser.getId()).onItem().transform(userBindRelations -> {
                            BindDashboadResponseDto dto = new BindDashboadResponseDto();
                            if (userBindRelations != null) {
                                dto.setAllBindCount(allBindCount);
                                int hasBindCount = userBindRelations.size();
                                dto.setHasBindCount(Long.valueOf(hasBindCount));
                                dto.setLeaveBindCount(allBindCount - hasBindCount);
                                return dto;
                            } else {
                                return dto;
                            }
                        });
                    } else {
                        throw new UserBindException("绑定失败");
                    }
                });
    }


    private Uni<LoginResponseDto> createLogonToken(SysUser user) {
        Uni<LoginResponseDto> transform = tokenService.generateToken(String.valueOf(user.getId()), user.getDevice_id())
                .onItem().transform(token -> buildLoginResponse(user, token));
        return transform;
    }

    //通过设备构造用户
    private static SysUser createUserByDevice(String deviceId, String channel) {
        SysUser newUser = SysUser.createByDevice(deviceId, channel);
        newUser.setNick_name(NicknameGenerator.generateNicknameWithPrefix("")); // 生成随机昵称
        return newUser;
    }

    private LoginResponseDto buildLoginResponse(SysUser appUser, String token) {
        LoginResponseDto response = new LoginResponseDto();
        response.setToken(token);
        response.setUserId(appUser.getId());
        response.setNickName(appUser.getNick_name());
        response.setUserLevel(appUser.getLevel());
        return response;
    }

    /**
     * 获取用户信息
     */
    public Uni<UserInfoDto> getUserInfo(Long appUserId) {
        return sysUserRepository.findByUserId(appUserId)
                .onItem().transformToUni(appUser -> {
                    if (appUser == null) {
                        return Uni.createFrom().failure(new RuntimeException("用户不存在"));
                    } else {
                        UserInfoDto dto = new UserInfoDto();
                        dto.setUserId(appUser.getId());
                        dto.setChannel(appUser.getChannel());
                        dto.setUserLevel(appUser.getLevel());
                        dto.setNickName(appUser.getNick_name());
                        dto.setDeviceId(appUser.getDevice_id());
                        return Uni.createFrom().item(dto);
                    }
                });
    }

    /**
     * 登出
     */
    public Uni<Void> logout(String token) {
        return tokenService.deleteToken(token);
    }

    /**
     * 验证密码
     *
     * @param inputPassword  输入的密码
     * @param storedPassword 数据库中存储的密码（MD5值）
     * @return 是否匹配
     */
    private boolean validatePassword(String inputPassword, String storedPassword) {
        try {
            String inputMd5 = calculateMD5(inputPassword);
            return inputMd5.equals(storedPassword);
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 计算字符串的MD5值
     *
     * @param input 输入字符串
     * @return MD5值
     */
    private String calculateMD5(String input) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] messageDigest = md.digest(input.getBytes());

            StringBuilder hexString = new StringBuilder();
            for (byte b : messageDigest) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) {
                    hexString.append('0');
                }
                hexString.append(hex);
            }
            return hexString.toString();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("MD5算法不可用", e);
        }
    }
}